home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-06-17 | 12.2 KB | 408 lines | [TEXT/MPS ] |
- { 'Slider' is the mental product of Bill Johnson & Ron Duritsch
- notes: put the accompanying sound file in your system folder for maximum effect }
-
- {$R+} { range checking }
-
- UNIT Drag;
-
-
- INTERFACE
-
- USES
- MemTypes, QuickDraw, OSIntf, ToolIntf, SANE;
-
- PROCEDURE DragIt;
-
-
- IMPLEMENTATION
-
- CONST
- nearInfinity = 32000;
- SlopSize = 25;
- OutOfBounds = $8000;
- allKeyEvents = keyDownMask + keyUpMask + autoKeyMask;
-
- TYPE
- WindArray = ARRAY[1..32] OF WindowPtr; { this data structure stores the window pointers that
- have been selected with the mouse. The first pointer
- in the array (WindArray[1]) must be the pointer to
- the selected window closest to the front window. }
-
- PROCEDURE Get3Cursors (VAR svCrs: Cursor; VAR hndCrs: Cursor; VAR scndCrs: Cursor); FORWARD;
- PROCEDURE GetScreenSize (topWind: windowPtr; VAR screenPerim: rect); FORWARD;
- FUNCTION LoadSound (VAR SoundBuffer: Ptr; VAR sndSize: longint): boolean; FORWARD;
- FUNCTION InsertWPtr(HitWPtr: windowPtr; VAR PtrArray: WindArray; VAR NumWind: integer): boolean; FORWARD;
- PROCEDURE SumWRgnsBelow (StartWPtr: windowPtr; DragRegion: RgnHandle); FORWARD;
- PROCEDURE MoveWindBelow (StartWPtr: windowPtr; hor, ver: integer; dragArea: rect); FORWARD;
- PROCEDURE MoveWindSel (VAR PtrArray: WindArray; NumWind, hor, ver: integer; dragArea: rect); FORWARD;
-
-
-
- PROCEDURE DragIt;
-
- VAR
- theEvent : EventRecord;
- WMgrPort, savePort : GrafPtr;
- HitWindPtr, topWindPtr : WindowPtr;
- currentWPeek : windowPeek;
- WPtrArray : WindArray;
- DragRgn, ExistClipRgn : RgnHandle;
- mousePos : Point;
- limitRect, slopRect : rect;
- screenBounds, dragLim : rect;
- thePart , index : integer;
- NumWSel, vMov, hMov : integer;
- mainCursor, saveCursr : Cursor;
- secondCursor : Cursor;
- DropOut, haveSound : boolean;
- SoundPointer : Ptr;
- sndSize, longPos : longint;
-
- BEGIN
- topWindPtr := FrontWindow; { this does not change }
-
- GetPort(savePort);
- DragRgn := NewRgn;
- ExistClipRgn := NewRgn;
- GetClip(ExistClipRgn);
-
- GetScreenSize (topWindPtr, screenBounds);
- dragLim := screenBounds;
- InsetRect (dragLim, 20, 0);
-
- GetWMgrPort(WMgrPort);
- SetPort(WMgrPort);
- SetPortBits(WMgrPort^.portBits);
- ClipRect(WMgrPort^.portRect);
-
- Get3Cursors (saveCursr, mainCursor, secondCursor);
- SetCursor (mainCursor);
-
- haveSound := LoadSound (SoundPointer, sndSize);
-
- NumWSel := 0;
- DropOut := FALSE;
- WPtrArray[1] := topWindPtr; { init to FrontWindow to prevent 'ClipAbove' call when no windows sel }
-
- REPEAT
- IF GetNextEvent(mDownMask, theEvent) then begin
- mousePos := theEvent.where;
- thePart := FindWindow (theEvent.where, hitWindPtr);
-
- IF (haveSound)
- then StartSound (SoundPointer, sndSize, NIL); { play asynchronous sound }
-
- if (thePart < inSysWindow)
- then begin
- sysBeep (1);
- Dropout := TRUE;
- end
- else begin
- if (BitAnd(theEvent.modifiers, shiftKey) <> 0)
- then begin
- if (InsertWPtr(HitWindPtr, WPtrArray, NumWSel))
- then begin
- SetCursor (secondCursor);
- currentWPeek := WindowPeek (HitWindPtr);
- UnionRgn (currentWPeek^.StrucRgn, DragRgn, DragRgn);
- end;
- end
- else begin
- Dropout := TRUE;
- if (BitAnd(theEvent.modifiers, optionKey) <> 0)
- then begin
- SetRectRgn (DragRgn, 0, 0, 0, 0); { empty region of accumulated regions }
- SumWRgnsBelow (hitWindPtr, DragRgn);
- WPtrArray[1] := hitWindPtr;
- end
- else begin
- if (NumWSel = 0)
- then SumWRgnsBelow (topWindPtr, DragRgn)
- else begin
- if (InsertWPtr(HitWindPtr, WPtrArray, NumWSel))
- then begin
- SetCursor (secondCursor);
- currentWPeek := WindowPeek (HitWindPtr);
- UnionRgn (currentWPeek^.StrucRgn, DragRgn, DragRgn);
- end;
- end;
- end;
- end;
-
- ClipRect(WMgrPort^.portRect);
- if (WPtrArray[1] <> topWindPtr) { top selected window must be in 'WPtrArray[1]' }
- then ClipAbove (WindowPeek (WPtrArray[1]));
-
- IF (BitAnd(theEvent.modifiers, cmdKey) <> 0)
- then SetRect (dragLim, -nearInfinity, -nearInfinity, nearInfinity, nearInfinity);
- with dragLim do begin
- SetRect (limitRect, left, top, right, bottom);
- SetRect (slopRect, left - SlopSize, top - 45, right + SlopSize, bottom + SlopSize);
- end;
-
- longPos := DragGrayRgn (DragRgn, mousePos, limitRect, slopRect, 0, NIL);
-
- IF (longPos <> OutOfBounds) then begin
- hMov := LoWord (longPos);
- vMov := HiWord (longPos);
- IF (BitAnd(theEvent.modifiers, shiftKey) <> 0)
- then begin
- IF (ABS (hMov) + ABS (vMov) > 5) then begin
- Dropout := TRUE;
- MoveWindSel (WPtrArray, NumWSel, hMov, vMov, dragLim);
- end;
- end
- else begin
- IF (BitAnd(theEvent.modifiers, optionKey) <> 0)
- then MoveWindBelow (hitWindPtr, hMov, vMov, dragLim)
- else begin
- if (NumWSel = 0)
- then MoveWindBelow (topWindPtr, hMov, vMov, dragLim)
- else MoveWindSel (WPtrArray, NumWSel, hMov, vMov, dragLim);
- end;
- end;
- end; { IF (longPos <> OutOfBounds) ... }
- end; { if (thePart < inSysWindow)... }
- SetCursor (mainCursor);
- end;
- UNTIL Dropout;
-
- IF (haveSound)
- then DisposPtr (SoundPointer);
- SetPort (savePort);
- SetClip (ExistClipRgn);
- DisposeRgn (ExistClipRgn);
- DisposeRgn (DragRgn);
- flushEvents (allKeyEvents, 0); { in case the user re-selected the FKEY while we were in here }
- SetCursor (saveCursr);
- END;
-
-
-
-
- PROCEDURE Get3Cursors (VAR svCrs: Cursor; VAR hndCrs: Cursor; VAR scndCrs: Cursor);
- CONST
- LoMemCrsrLoc = $844;
- VAR
- CrsrPtr : ^Cursor;
- BEGIN
- CrsrPtr := pointer (LoMemCrsrLoc);
- svCrs := CrsrPtr^;
-
- StuffHex (ptr (@hndCrs), 'AAAA0000B030334E' );
- StuffHex (ptr (longint (@hndCrs) + 8), '84C954C982490249');
- StuffHex (ptr (longint (@hndCrs) + 16), '8D01130091000800');
- StuffHex (ptr (longint (@hndCrs) + 24), '8400040082004100');
- StuffHex (ptr (longint (@hndCrs) + 32), 'AAAA0000B030337E');
- StuffHex (ptr (longint (@hndCrs) + 40), '87FF57FF83FF03FF');
- StuffHex (ptr (longint (@hndCrs) + 48), '8FFF1FFF9FFF0FFF');
- StuffHex (ptr (longint (@hndCrs) + 56), '87FF07FF83FF41FF');
- StuffHex (ptr (longint (@hndCrs) + 64), '00050007');
-
- StuffHex (ptr (@scndCrs), '000000000030034E' );
- StuffHex (ptr (longint (@scndCrs) + 8), '04C904C902490249');
- StuffHex (ptr (longint (@scndCrs) + 16), '0D01130011000800');
- StuffHex (ptr (longint (@scndCrs) + 24), '0400040002000100');
- StuffHex (ptr (longint (@scndCrs) + 32), '000000000030037E');
- StuffHex (ptr (longint (@scndCrs) + 40), '07FF07FF03FF03FF');
- StuffHex (ptr (longint (@scndCrs) + 48), '0FFF1FFF1FFF0FFF');
- StuffHex (ptr (longint (@scndCrs) + 56), '07FF07FF03FF01FF');
- StuffHex (ptr (longint (@scndCrs) + 64), '00050007');
- END;
-
-
-
-
- PROCEDURE GetScreenSize (topWind: windowPtr; VAR screenPerim: rect);
- TYPE
- WStatePtr = ^WStateData;
- WStateHdl = ^WStatePtr;
- VAR
- windRect : rect;
- ZoomDataHdl : WStateHdl;
- tempWindPtr : windowPtr;
- BEGIN
- SetRect (windRect, 40, 0, 100, 100);
- tempWindPtr := NewWindow (nil, windRect, 'x', FALSE, 8, topWind, TRUE, 0);
- ZoomDataHdl := WStateHdl (WindowPeek (tempWindPtr)^.dataHandle);
- screenPerim.left := ZoomDataHdl^^.stdState.left - 2;
- screenPerim.top := ZoomDataHdl^^.stdState.top;
- screenPerim.Right := ZoomDataHdl^^.stdState.right + 2;
- screenPerim.Bottom := ZoomDataHdl^^.stdState.bottom + 2;
- disposeWindow (tempWindPtr);
- END;
-
-
-
-
- FUNCTION LoadSound (VAR SoundBuffer: Ptr; VAR sndSize: longint): boolean;
- { This code trys to load a sound file. To allow some selection of playback rate, it will look for 2
- different files. If it finds a file called Sound22, it will load/play it at a sampling rate of 22 kHz.
- If thats not found, it will look for Sound11, and if found it will be played at 11 kHz. }
- VAR
- FFSound : FFSynthPtr;
- soundRef : integer;
- rateDiv, rc : integer;
- Count, fSize : longint;
- BEGIN
- rateDiv := 1; { assume 22 kHz sampling }
- LoadSound := FALSE;
- rc := FSOpen ('Sound22', 0, soundRef);
- IF (rc <> noErr) THEN BEGIN
- rateDiv := 2; { set for 11 kHz playback }
- rc := FSOpen ('Sound11', 0, soundRef);
- END;
-
- IF (rc = noErr)
- THEN BEGIN
- LoadSound := TRUE;
- rc := GetEOF( soundRef, fSize ); { get file size }
- sndSize := fSize + 6; { size of sound buffer }
- SoundBuffer := NewPtr (sndSize);
- FFSound := FFSynthPtr (SoundBuffer);
- FFSound^.mode := ffMode; { free form synthesizer }
- FFSound^.count := FixRatio (1, rateDiv); { fill in the fixed binary playback rate }
- Count := fSize;
- rc := FSRead (soundREf, Count, @FFSound^.waveBytes);
- rc := FSClose (soundRef);
- END;
- END;
-
-
-
- FUNCTION InsertWPtr(HitWPtr : windowPtr;
- VAR PtrArray : WindArray;
- VAR NumWind : integer): boolean;
- { purpose _IF_ ptr not in list, put window ptr 'HitWPtr' in list 'PtrArray' & add 1 to 'NumWind'
- ALWAYS keep ptr to highest selected window in 'PtrArray[1]' }
- VAR
- ctr : integer;
- match : boolean;
- cWPeek : windowPeek;
- cWPtr : WindowPtr;
- HiPtr : WindowPtr;
- BEGIN
- if (NumWind = 0)
- then begin
- NumWind := 1;
- PtrArray[1] := HitWPtr;
- InsertWPtr := TRUE;
- end
- else begin
- ctr := 0;
- REPEAT
- ctr := ctr + 1;
- match := (HitWPtr = PtrArray[ctr]);
- UNTIL (ctr = NumWind) or (match);
-
- if (match)
- then InsertWPtr := FALSE
- else begin
- NumWind := NumWind + 1;
- InsertWPtr := TRUE;
-
- HiPtr := PtrArray[1];
- cWPtr := HitWPtr;
- REPEAT
- cWPeek := WindowPeek (cWPtr);
- cWPtr := windowPtr(cWPeek^.nextWindow);
- UNTIL (cWPtr = HiPtr) or (cWPtr = NIL);
- if (cWPtr = HiPtr)
- then begin
- PtrArray[NumWind] := HiPtr;
- PtrArray[1] := HitWPtr;
- end
- else PtrArray[NumWind] := HitWPtr;
- end;
- end;
- END;
-
-
- PROCEDURE SumWRgnsBelow (StartWPtr: windowPtr; DragRegion: RgnHandle);
- { purpose return in 'DragRegion' a region including all windows after & incl. window 'StartWPtr' }
- VAR
- currWPeek : windowPeek;
- PrevWPeek : windowPeek;
- currWindPtr : WindowPtr;
- BEGIN
- currWindPtr := StartWPtr;
- REPEAT
- currWPeek := WindowPeek (currWindPtr);
- UnionRgn (currWPeek^.StrucRgn, DragRegion, DragRegion);
- PrevWPeek := currWPeek;
- currWindPtr := windowPtr(PrevWPeek^.nextWindow);
- UNTIL (currWindPtr = NIL);
- END;
-
-
-
- PROCEDURE MoveWindBelow (StartWPtr : windowPtr;
- hor, ver : integer;
- dragArea : rect);
- { purpose move windows -> 'StartWPtr' to last window in the window list by 'hor','ver' }
- VAR
- PrevWPeek : windowPeek;
- currWindPtr : WindowPtr;
- origLoc : point;
- leftBound : integer;
- BEGIN
- currWindPtr := StartWPtr;
- REPEAT
- SetPort (grafPtr(currWindPtr));
- origLoc := currWindPtr^.portrect.topleft;
- LocalToGlobal (origLoc);
- origLoc.h := origLoc.h + hor;
- origLoc.v := origLoc.v + ver;
- IF (origLoc.v < dragArea.top)
- then origLoc.v := dragArea.top;
- if (origLoc.v > dragArea.bottom)
- then origLoc.v := dragArea.bottom;
- leftBound := dragArea.left - GrafPtr(currWindPtr)^.portRect.right
- + GrafPtr(currWindPtr)^.portRect.left;
- if (origLoc.h < leftBound)
- then origLoc.h := leftBound;
- if (origLoc.h > dragArea.right)
- then origLoc.h := dragArea.right;
- MoveWindow(currWindPtr, origLoc.h, origLoc.v, FALSE);
- PrevWPeek := WindowPeek(currWindPtr);
- currWindPtr := windowPtr(PrevWPeek^.nextWindow);
- UNTIL (currWindPtr = NIL);
- END;
-
-
-
- PROCEDURE MoveWindSel (VAR PtrArray : WindArray;
- NumWind : integer;
- hor, ver : integer;
- dragArea : rect);
- { purpose move windows in list 'PtrArray' by 'hor' & 'ver' }
- VAR
- origLoc : point;
- index : integer;
- leftBound : integer;
- BEGIN
- FOR index := 1 to NumWind DO begin
- SetPort (grafPtr(PtrArray[index]));
- origLoc := PtrArray[index]^.portrect.topleft;
- LocalToGlobal (origLoc);
- origLoc.h := origLoc.h + hor;
- origLoc.v := origLoc.v + ver;
- IF (origLoc.v < dragArea.top)
- then origLoc.v := dragArea.top;
- if (origLoc.v > dragArea.bottom)
- then origLoc.v := dragArea.bottom;
- leftBound := dragArea.left - GrafPtr(PtrArray[index])^.portRect.right
- + GrafPtr(PtrArray[index])^.portRect.left;
- if (origLoc.h < leftBound)
- then origLoc.h := leftBound;
- if (origLoc.h > dragArea.right)
- then origLoc.h := dragArea.right;
- MoveWindow (PtrArray[index], origLoc.h, origLoc.v, FALSE);
- end;
- END;
-
-
-
- END.
-
-